package config

import (
	"errors"
	"fmt"
	fun "gitee.com/jishulang/go-fun"
	"os"
	"reflect"
	"strconv"
)

func envCreate(env *string) {
	defer func() {
		fmt.Println("env:", *env)
	}()
	if *env != "" {
		return
	}
	*env = "local"

	//
	filePath := fmt.Sprintf("%s/.env", CONFIG_DIR)
	is, _ := fun.FileIsExist(filePath)
	fmt.Println(filePath, is)
	if !is {
		fun.FilePutContents(filePath, "Environment=")
	}
	for _, e := range envArr {
		filePath = fmt.Sprintf("%s/.env.%s", CONFIG_DIR, e)
		is, _ = fun.FileIsExist(filePath)
		fmt.Println(filePath, is)
		content := ""
		if !is {
			content = fmt.Sprintf("Environment=%s", e)
			fun.FilePutContents(filePath, content)
		}
	}
}

// 从环境变量中加载配置
func envFrom(conf interface{}) error {
	v := reflect.ValueOf(conf).Elem()
	err := envFromFor(v)
	if err != nil {
		msg := fmt.Sprintf("[NewConfig]envFrom err:%s", err.Error())
		panic(msg)
	}
	return envFromFor(v)
}

func envFromFor(v reflect.Value) error {
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		if err := envFromField(t, i, v); err != nil {
			return err
		}
	}
	return nil
}

func envFromField(t reflect.Type, i int, v reflect.Value) error {
	field := t.Field(i)
	envTag := field.Tag.Get("env")
	if envTag == "" && field.Type.Kind() != reflect.Struct {
		return nil // 如果当前字段不是结构体类型，则跳过
	}

	envValue := os.Getenv(envTag)
	if envValue == "" && field.Type.Kind() != reflect.Struct {
		return nil // 如果当前字段不是结构体类型，则跳过
	}

	switch field.Type.Kind() {
	case reflect.String:
		v.Field(i).SetString(envValue)
	case reflect.Int, reflect.Int64:
		val, err := strconv.ParseInt(envValue, 10, 64)
		if err != nil {
			return err
		}
		v.Field(i).SetInt(val)
	case reflect.Uint, reflect.Uint64:
		val, err := strconv.ParseUint(envValue, 10, 64)
		if err != nil {
			return err
		}
		v.Field(i).SetUint(val)
	case reflect.Bool:
		val, err := strconv.ParseBool(envValue)
		if err != nil {
			return err
		}
		v.Field(i).SetBool(val)
	case reflect.Float32, reflect.Float64:
		val, err := strconv.ParseFloat(envValue, 64)
		if err != nil {
			return err
		}
		v.Field(i).SetFloat(val)
	case reflect.Struct:
		return envFromFor(v.Field(i)) // 如果是结构体类型，递归处理
	default:
		return fmt.Errorf("unsupported type: %s", field.Type)
	}
	return nil
}

// 验证必填字段
func verifyBinding(conf interface{}) {
	v := reflect.ValueOf(conf).Elem()
	err := verifyBindingFor(v)
	if err != nil {
		msg := fmt.Sprintf("[NewConfig]verifyBinding:%s", err.Error())
		panic(msg)
	}
}

func verifyBindingFor(v reflect.Value) error {
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		if err := verifyBindingField(t, i, v); err != nil {
			return err
		}
	}
	return nil
}

func verifyBindingField(t reflect.Type, i int, v reflect.Value) error {
	field := t.Field(i)
	requiredTag := field.Tag.Get("required")

	// 检查字段是否有"required"标签
	if requiredTag == "true" {
		if !hasValue(v.Field(i)) {
			msg := fmt.Sprintf("%s is required", field.Name)
			return errors.New(msg)
		}
	}

	// 如果是结构体类型，递归检查
	if field.Type.Kind() == reflect.Struct {
		return verifyBindingFor(v.Field(i))
	}

	return nil
}

func hasValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.String:
		return v.String() != ""
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() != 0
	case reflect.Float32, reflect.Float64:
		return v.Float() != 0.0
	case reflect.Bool:
		return v.Bool()
	case reflect.Slice, reflect.Map:
		return v.Len() > 0
	case reflect.Ptr, reflect.Interface:
		return !v.IsNil()
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			if hasValue(v.Field(i)) {
				return true
			}
		}
		return false
	default:
		return !v.IsZero()
	}
}
